using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading;
using LastFmLib.API20.Types;
using LastFmLib.API20.User;
using StaffWarsFm.Lib.Data;
using StaffWarsFm.Lib.Services;

namespace StaffWarsFm.Questions
{
    public class QuestionService : IQuestionService
    {
        private int _retrys;
        private AlbumQuestionService _albumService = new AlbumQuestionService();
        private ArtistQuestionService _artistService = new ArtistQuestionService();
        private List<QuestionServiceBase> _questionServices = new List<QuestionServiceBase>
        {
            new AlbumQuestionService(),
            new ArtistQuestionService(),
            new ArtworkQuestionService(),
            new BiggestFanQuestionService()
        };

        public Question[] GenerateQuestion(User[] players, User[] connectedUsers, int count)
        {
            
            CacheStatus.CurrentUsers = connectedUsers;
            var questions = new List<Question>();

            while (questions.Count < count)
            {
                var question = GenerateQuestion(players, connectedUsers);

                if (0 == questions.Count(q => q.Text == question.Text))
                {
                    questions.Add(question);
                }
            }

            return questions.ToArray();
        }

        public Question GenerateQuestion(User[] players, User[] connectedUsers)
        {
            CacheStatus.CurrentUsers = connectedUsers;
            var artist = _artistService.GetTopArtist(players);

            try
            {
                var question = _questionServices[Util.Random(_questionServices.Count)]
                    .GenerateQuestion(artist, players, connectedUsers);

                _retrys = 0;

                return question;
            }
            catch(Exception ex)
            {
                _retrys++;

                if(_retrys > 4)
                {
                    throw;
                }

                return GenerateQuestion(players, connectedUsers);
            }
        }

        public void PopulateCache(IEnumerable<User> users)
        {
            if (false == CacheStatus.ArtistCachePopulated)
            {
                new Thread(() => PopulateArtistCache(users)).Start();
            }

            if (false == CacheStatus.AlbumCachePopulated)
            {
                new Thread(() => PopulateAlbumCache(users)).Start();
            }
        }

        private void PopulateArtistCache(IEnumerable<User> users)
        {
            foreach (var user in users)
            {
                var getArtists = new UserGetTopArtists(user.UserName, LastFmLib.API20.modEnums.ChartPeriod.TwelveMonths);

                getArtists.AuthData = Util.GetAuthData();
                getArtists.Start();

                if (getArtists.Succeeded)
                {
                    foreach (var artist in getArtists.Result)
                    {
                        if (false == Cache<ArtistInfo>.Contains(a => a.MbId.ToString() == artist.MbId.ToString()))
                        {
                            try
                            {
                                Cache<ArtistInfo>.Add(_artistService.GetArtistInfo(artist.MbId));
                            }
                            catch (Exception)
                            {
                                //bleep
                            }
                        }
                    }
                }
            }
            CacheStatus.ArtistCachePopulated = true;
        }

        private void PopulateAlbumCache(IEnumerable<User> users)
        {
            foreach (var user in users)
            {
                var getAlbums = new UserGetTopAlbums(user.UserName, LastFmLib.API20.modEnums.ChartPeriod.TwelveMonths);

                getAlbums.AuthData = Util.GetAuthData();
                getAlbums.Start();

                if (getAlbums.Succeeded)
                {
                    foreach (var album in getAlbums.Result)
                    {
                        if (false == Cache<AlbumInfo>.Contains(a => a.MbId == album.MbId))
                        {
                            try
                            {
                                Cache<AlbumInfo>.Add(_albumService.GetAlbumInfo(album.MbId));
                            }
                            catch (Exception)
                            {
                                //moo
                            }
                        }
                    }
                }
            }
            CacheStatus.AlbumCachePopulated = true;
        }
    }
}
